package com.koron.css2.workflow;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.koron.css2.baseConfig.bean.BaseRLSJBean;
import com.koron.css2.baseConfig.impl.BaseRLSJUpdate;
import com.koron.css2.baseConfig.mapper.BaseRLSJMapper;
import com.koron.css2.baseConfig.mapper.ConfigMapper;
import com.koron.css2.clientCenter.bean.*;
import com.koron.css2.clientCenter.impl.OpenUserAdd;
import com.koron.css2.clientCenter.mapper.*;
import com.koron.css2.contractmanage.mapper.ContractManageMapper;
import com.koron.css2.contractmanage.vo.ContractManageVO;
import com.koron.css2.meterService.mapper.MsInfoMapper;
import com.koron.css2.newProjectCenter.bean.*;
import com.koron.css2.newProjectCenter.bean.query.PjInfoQueryBean;
import com.koron.css2.newProjectCenter.bean.query.PjMeterQuery;
import com.koron.css2.newProjectCenter.impl.PjSave;
import com.koron.css2.newProjectCenter.impl.pubUpTime.WorkDayUtils;
import com.koron.css2.newProjectCenter.mapper.PjInfoMapper;
import com.koron.css2.newProjectCenter.mapper.PjMeterMapper;
import com.koron.css2.newProjectCenter.service.PjInfoService;
import com.koron.css2.serviceManage.bean.UserDiscountBean;
import com.koron.css2.serviceManage.bean.UserInfoBean;
import com.koron.css2.serviceManage.bean.UserMixtureBean;
import com.koron.css2.serviceManage.mapper.UserDiscountMapper;
import com.koron.css2.serviceManage.mapper.UserMixtureMapper;
import com.koron.css2.serviceManage.queryBean.UserMixtureQueryBean;
import com.koron.css2.workflow.bean.NextTaskNodeInfoBean;
import com.koron.css2.workflow.bean.NodeInfoBean;
import com.koron.util.Constant;
import com.koron.util.DBSourceUtils;
import com.koron.util.DateUtils;
import com.koron.util.Tools;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.swan.bean.MessageBean;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 工程报装-流程提交
 *
 * @author admin
 * @version 2.1
 * @since today
 */
public class PjProcessCommit extends AbstractProcessCommit {

    private static Logger log = LoggerFactory.getLogger(PjProcessCommit.class);

    //数据来源网厅
    private static final String SOURCE_INTERNET = "2";

    //数据来源微厅
    private static final String SOURCE_WECHAT = "3";

    private static final String CONTRACT_STATUS = "2";

    //合同类型 默认为：1（0-电子供水合同/1-普通供水合同/2-电子施工合同/3-普通施工合同）
    private static final String CONTRACT_TYPE = "1";

    /**
     * 流程审批提交前的判断
     */
    @Override
    public MessageBean<?> before(SessionFactory factory, UserInfoBean userInfo, Map<String, String> param) {
        ContractManageMapper contractManageMapper = factory.getMapper(ContractManageMapper.class);
        MessageBean<Void> info = MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "success", Void.class);
        String receiptType = param.get("receiptType");
        if (StringUtils.isEmpty(receiptType)) {
            info.setCode(Constant.MESSAGE_INT_FAIL);
            info.setDescription("单据类型不能为空");
            return info;
        }
        ConfigMapper configMapper = factory.getMapper(ConfigMapper.class);
        if (receiptType.startsWith(PjInfoService.PROJECT_INFO_NEW_RECEIPT)) {
            String PJ_APPROVAL_COMMENT = configMapper.getConfigValueByName("PJ_APPROVAL_COMMENT");
            if (Objects.equals("1", PJ_APPROVAL_COMMENT) && StringUtils.isBlank(param.get("comment"))) {
                info.setCode(Constant.MESSAGE_INT_FAIL);
                info.setDescription("审批意见不能为空!");
                return info;
            }
        }
        if (receiptType.startsWith(PjInfoService.PROJECT_INFO_NEW_RECEIPT)) {
            PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);
            PjInfoQueryBean pjInfoQueryBean = new PjInfoQueryBean();
            pjInfoQueryBean.setId(param.get("billId"));
            PjInfoBean pjInfoBean = pjInfoMapper.getSingle(pjInfoQueryBean);
            String fromNodeCode = pjInfoBean.getProcessState();
            // 假如当前节点是施工勘察，并且工程类型为 【居民】以及【企业】，如果未添加水表则需要进行提示水表明细不能为空
            if (Objects.equals(fromNodeCode, PjInfoService.SURVEY)
                    && (Objects.equals(PjInfoBean.PJ_TYPE_1, pjInfoBean.getPjType())
                    || Objects.equals(PjInfoBean.PJ_TYPE_5, pjInfoBean.getPjType()))) {
                PjMeterMapper pjMeterMapper = factory.getMapper(PjMeterMapper.class);
                List<PjMeter> pjMeterList = pjMeterMapper.getListByConsultId(pjInfoBean.getId());
                if (pjMeterList.size() == 0) {
                    return MessageBean.create(Constant.MESSAGE_INT_FAIL, "请先保存水表明细", String.class);
                }
            }
            // 编制结算页面的数据状态为审批和结束节点时，流程不允许保存和提交
            if (StringUtils.equals(fromNodeCode, PjInfoService.PJSETTLEMENT) || StringUtils.equals(fromNodeCode, PjInfoService.PJPAYMENT)) {
                MessageBean message = PjSave.verifyPjSettlement(factory, pjInfoBean);
                if (Constant.MESSAGE_INT_SUCCESS != message.getCode()) {
                    return message;
                }
            }

            if (StringUtils.isNotEmpty(pjInfoBean.getProcessInstanceId()) && fromNodeCode.equals(PjInfoService.REGISTER_ACCOUNT)) {
                String billId = pjInfoBean.getId();
                String processInstanceId = pjInfoBean.getProcessInstanceId();
                Map map = JSONUtil.toBean(JSONUtil.toJsonStr(param.get("formVariables")), Map.class);
                Map<String, Object> nextTaskInfo = WorkflowImpl.getNextTaskInfo(map, processInstanceId);
                String toNodeCode = String.valueOf(nextTaskInfo.get("taskCode"));

                // 立户审批
                //兼容会审
                if (fromNodeCode.equals(PjInfoService.REGISTER_ACCOUNT)
                        && Integer.valueOf(param.get("operation")) == ProcessInterface.OPERATION_AGREE
                        && !toNodeCode.equals(PjInfoService.REGISTER_ACCOUNT)) {
                    PjMeterMapper pjMeterMapper = factory.getMapper(PjMeterMapper.class);
                    CtmInfoMapper ctmInfoMapper = factory.getMapper(CtmInfoMapper.class);
                    AccountInfoMapper accountInfoMapper = factory.getMapper(AccountInfoMapper.class);
                    UserInfoMapper userInfoMapper = factory.getMapper(UserInfoMapper.class);
                    MsInfoMapper msInfoMapper = factory.getMapper(MsInfoMapper.class);
                    ChangeUserMapper changeUserMapper = factory.getMapper(ChangeUserMapper.class);
                    UserPersonDetailMapper userPersonDetailMapper = factory.getMapper(UserPersonDetailMapper.class);
                    UserMixtureMapper userMixtureMapper = factory.getMapper(UserMixtureMapper.class);
                    UserDiscountMapper userDiscountMapper = factory.getMapper(UserDiscountMapper.class);

                    // 1. 查出所有的立户所需信息
                    PjMeterQuery pjMeterQuery = new PjMeterQuery();
                    pjMeterQuery.setConsultId(billId);
                    List<PjMeter> pjMeterList = pjMeterMapper.getList(pjMeterQuery);
                    // 查出立户驳回标志
                    Integer registerAccountRejectFlag = pjInfoBean.getRegisterAccountRejectFlag();
                    // 立户用户编号列表，用于记录可能需要生成制卡单的用户编号列表
                    List<String> openUserNoList = Lists.newArrayList();
                    for (PjMeter pjMeter : pjMeterList) {
                        //获取容量水价配置
                        BaseRLSJMapper rlsjMapper = factory.getMapper(BaseRLSJMapper.class);

                        List<BaseRLSJBean> rlsjs = rlsjMapper.selectAll();

                        List<UserPersonDetailBean> userPersonDetailBeanList = new ArrayList<>();
                        // 查出立户驳回标志

                        // 5. 先查出临时用户数据 
                        UserBean userBeanTemp = userInfoMapper.getUserInfoById(pjMeter.getUserInfoTempId(), UserBean.USERTEMP);
                        CtmInfoBean ctmInfoTemp = ctmInfoMapper.getCtmInfoById(pjMeter.getUserCtmTempId(), CtmInfoBean.CTMTEMP);
                        AccountInfoBean accountInfoTemp = accountInfoMapper.getAccountInfoById(pjMeter.getUserAccountTempId(), AccountInfoBean.ACCOUNTTEMP);
                        // 6. 更新用户临时表的客户和账户信息
                        userBeanTemp.setCtmNo(ctmInfoTemp.getCtmNo());
                        userBeanTemp.setAccountNo(accountInfoTemp.getAccountNo());
                        // 将立户日期置为当天
                        userBeanTemp.setOpenDate(Tools.getCurrentDate());
                        userInfoMapper.userInfoUpdate(userBeanTemp, UserBean.USERTEMP);
                        // 6.1 ctmName,certNo,certType,likeTel,mobile,faxNumber,ctmAddr
                        OpenUserAdd openUserAdd = new OpenUserAdd();
                        openUserAdd.ctmInfoToUserInfo(ctmInfoTemp, userBeanTemp);
                        // 7. 检查正式表中用户是否已存在，不存在则生成
                        UserBean userBean = userInfoMapper.getUserInfoByUserNo(userBeanTemp.getUserNo(), UserBean.USER);
                        CtmInfoBean ctmInfoBean = ctmInfoMapper.getCtmInfoByCtmNo(ctmInfoTemp.getCtmNo(), CtmInfoBean.CTM);
                        AccountInfoBean accountInfo = accountInfoMapper.getAccountInfoByCode(accountInfoTemp.getAccountNo(), AccountInfoBean.ACCOUNT);
                        if (StringUtils.isNotEmpty(userBeanTemp.getContractNo())) {
                            // 通过合同编号查询是否存在合同签订记录
                            ContractManageVO gscontractManageVO = contractManageMapper.ContractNoInfo(userBeanTemp.getContractNo());
                            // 假如合同签订记录不为空，这种情况是用户在线上签订了合同，比如：电子合同
                            if (gscontractManageVO != null) {
                                userBeanTemp.setContractStatus(gscontractManageVO.getContractStatus());
                                // 合同签署日期为空就默认为当天
                                if (gscontractManageVO.getContractDate() == null) {
                                    userBeanTemp.setContractDate(DateUtils.parseDate(new Date(), "yyyy-MM-dd"));
                                } else {
                                    userBeanTemp.setContractDate(gscontractManageVO.getContractDate());
                                }

                                // 设置合同类型
                                userBeanTemp.setContractType(gscontractManageVO.getContractType());
                            } else {
                                // 将合同签订状态置为已签订 主要是用户会在线下签订合同，然后在立户时将合同编号输入，这种情况也视为已签订合同
                                userBeanTemp.setContractStatus(CONTRACT_STATUS);
                                // 设置合同签订日期
                                userBeanTemp.setContractDate(DateUtils.parseDate(new Date(), "yyyy-MM-dd"));
                                // 默认合同类型为：供用水合同
                                userBeanTemp.setContractType(CONTRACT_TYPE);
                            }
                        }
                        if (userBean == null) {
                            userBeanTemp.setCreateInfo(userInfo);
                            // 将立户日期置为当天
                            userBeanTemp.setOpenDate(Tools.getCurrentDate());
                            userInfoMapper.userInfoAdd(userBeanTemp, UserBean.USER);
                        }
                        openUserNoList.add(userBeanTemp.getUserNo());
                        if (ctmInfoBean == null) {
                            ctmInfoTemp.setCreateInfo(userInfo);
                            ctmInfoMapper.ctmInfoAdd(ctmInfoTemp, CtmInfoBean.CTM);
                        }
                        // 4. 检查正式表中账户是否已存在，不存在则生成
                        if (accountInfo == null) {
                            accountInfoTemp.setCreateInfo(userInfo);
                            accountInfoTemp.setCtmNo(ctmInfoTemp.getCtmNo());
                            accountInfoMapper.accountInfoAdd(accountInfoTemp, AccountInfoBean.ACCOUNT);
                        }
                        // 4.1 如果是被驳回，则更新正式的账户信息
                        if (registerAccountRejectFlag != null && registerAccountRejectFlag == 1 || ObjectUtil.isNotNull(accountInfo)) {
                            accountInfoTemp.setUpdateInfo(userInfo);
                            accountInfoMapper.accountInfoUpdateByNo(accountInfoTemp, AccountInfoBean.ACCOUNT);
                        }

                        //根据配置表取容量水价并更新到定额费用表
                        BaseRLSJUpdate.calculateRLSJ(factory, userInfo, userBeanTemp, rlsjs);

                        // 7.1 如果是被驳回，则更新正式的用户信息
                        if (registerAccountRejectFlag != null && registerAccountRejectFlag == 1 || ObjectUtil.isNotNull(userBean)) {
                            userBeanTemp.setUpdateInfo(userInfo);
                            userInfoMapper.userInfoUpdateByUserNo(userBeanTemp, UserBean.USER);
                        }
                        if (registerAccountRejectFlag != null && registerAccountRejectFlag == 1 || ObjectUtil.isNotNull(ctmInfoBean)) {
                            ctmInfoBean.setUpdateInfo(userInfo);
                            ctmInfoMapper.ctmInfoUpdateByCtmNo(ctmInfoBean, CtmInfoBean.CTM);
                        }

                        // 8. 更新水表状态，用户编号（20220727--去除限制）
                        msInfoMapper.updateMsInfoStatus(userBeanTemp.getMeterNo(), 2);
                        msInfoMapper.updateMsInfoUserNo(userBeanTemp.getMeterNo(), userBeanTemp.getUserNo());
                        // 9. 添加三户关联信息
                        if (registerAccountRejectFlag == null) {
                            userInfoMapper.userRelationHstAdd(Tools.getObjectId(), userBeanTemp.getCtmNo(), userBeanTemp.getUserNo(), userBeanTemp.getAccountNo());
                        }
                        // 10. 更新用水人口到UserPersonDetail,循环结束后批量
                        List<UserChangePersonBean> userChangePersonBeanList = changeUserMapper.getUserChangePersonById(pjMeter.getConsultId());
                        for (UserChangePersonBean userChangePersonBean : userChangePersonBeanList) {
                            UserPersonDetailBean bean = new UserPersonDetailBean();
                            bean.setCreateInfo(userInfo);
                            bean.setUserNo(userBeanTemp.getUserNo());
                            bean.setCertNo(userChangePersonBean.getCertNo());
                            bean.setCertType(userChangePersonBean.getCertType());
                            bean.setName(userChangePersonBean.getName());
                            bean.setLinkTel(userChangePersonBean.getLinkTel());
                            bean.setComments(userChangePersonBean.getComments());
                            userPersonDetailBeanList.add(bean);
                        }
                        // 10.1 如果是被驳回，则删除原有的数据
                        if (registerAccountRejectFlag != null && registerAccountRejectFlag == 1) {
                            userPersonDetailMapper.userPersonDetailDelete(userBeanTemp.getUserNo());
                        }
                        // 11. 更新混合用水 (照抄的开户,OpenUserWorkFlow)
                        UserMixtureQueryBean userMixtureQueryBean = new UserMixtureQueryBean();
                        userMixtureQueryBean.setUserNo(userBeanTemp.getUserNo());
                        List<UserMixtureBean> userMixtureBeanList = userMixtureMapper.listTemp(userMixtureQueryBean);
                        if (userMixtureBeanList != null && userMixtureBeanList.size() > 0) {
                            List<UserMixtureBean> exists = userMixtureMapper.list(userMixtureQueryBean);
                            List<UserMixtureBean> mixtureBeans = new ArrayList<UserMixtureBean>();
                            mixtureBeans.addAll(exists);
                            for (UserMixtureBean userMixtureBean : userMixtureBeanList) {
                                int isExits = 0;
                                for (UserMixtureBean exist : exists) {
                                    // 不明白这个加这个判断的原因
                                    if (exist.getUseWaterType().equals(userMixtureBean.getUseWaterType()) && userMixtureBean.getCostNo().equals(exist.getCostNo())) {
                                        isExits = 1;
                                        userMixtureBean.setUpdateInfo(userInfo);
                                        userMixtureMapper.update(userMixtureBean);
                                        mixtureBeans.remove(exist);
                                    }
                                }
                                if (isExits == 0) {
                                    userMixtureBean.setCreateInfo(userInfo);
                                    if (StringUtils.isEmpty(userMixtureBean.getUserNo()))
                                        userMixtureBean.setUserNo(userBeanTemp.getUserNo());
                                    userMixtureMapper.insert(userMixtureBean);
                                }

                            }
                            for (UserMixtureBean mixtureBean : mixtureBeans) {
                                userMixtureMapper.delete(mixtureBean);
                            }
                            userMixtureMapper.deleteTempById(billId);
                        }
                        // 12. 更新费用折扣 (照抄的开户,OpenUserWorkFlow)
                        List<UserDiscountBean> discountBeanList = userDiscountMapper.listTemp(userMixtureQueryBean);
                        if (discountBeanList != null && discountBeanList.size() > 0) {
                            List<UserDiscountBean> existslist = userDiscountMapper.list(userMixtureQueryBean);
                            List<UserDiscountBean> discountBeans = new ArrayList<UserDiscountBean>();
                            discountBeans.addAll(existslist);
                            for (UserDiscountBean userDiscountBean : discountBeanList) {
                                int isExits = 0;
                                for (UserDiscountBean exist : existslist) {
                                    // 不明白这个加这个判断的原因
                                    if (exist.getCostId().equals(userDiscountBean.getCostId())) {
                                        isExits = 1;
                                        userDiscountBean.setUpdateInfo(userInfo);
                                        userDiscountMapper.update(userDiscountBean);
                                        discountBeans.remove(exist);
                                    }
                                }
                                if (isExits == 0) {
                                    userDiscountBean.setCreateInfo(userInfo);
                                    if (StringUtils.isEmpty(userDiscountBean.getUserNo()))
                                        userDiscountBean.setUserNo(userBeanTemp.getUserNo());
                                    userDiscountMapper.insert(userDiscountBean);
                                }

                            }
                            for (UserDiscountBean discountBean : discountBeans) {
                                userDiscountMapper.delete(discountBean);
                            }
                            userDiscountMapper.deleteTempById(billId);
                        }
                        // 14. 新增UserPersonDetail数据
                        if (registerAccountRejectFlag == null) {
                            if (userPersonDetailBeanList != null && userPersonDetailBeanList.size() > 0) {
                                userPersonDetailMapper.userPersonDetailAddList(userPersonDetailBeanList);
                            }
                        }
                    }
                    if (CollectionUtil.isNotEmpty(openUserNoList)) {
                        //如果配置了开户后，自动生成制卡登记，则审批结束后自动生成制卡登记
                        String autoRegisterMakeConfig = Tools.getConfigValue(DBSourceUtils.getDbEnv(userInfo.getCurWaterCode()),
                                "AUTO_REGISTER_MAKE_CARD_AFTER_OPEN");
                        if (UserWaterCardBean.AUTO_REGISTER_MAKE_AFTER_OPEN.equals(autoRegisterMakeConfig)) {
                            UserWaterCardBean.registerMultipleUserWaterCard(factory, userInfo, openUserNoList, true);
                        }
                    }
                }
            }
        }
        return info;
    }

    @Override
    public void after(SessionFactory factory, UserInfoBean userInfo, Map<String, String> param, NextTaskNodeInfoBean nextTaskInfo) {
        String toNodeCode = "";
        String fromNodeCode = nextTaskInfo.getPreNodeCode();
        List<NodeInfoBean> nodeInfos = nextTaskInfo.getCurNodes();
        if (nodeInfos.size() > 0) {
            toNodeCode = nodeInfos.get(0).getCode();
        }
        //如果数据来源是微厅与网厅，需要视情况修改驳回状态overruleFlag的值
        PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);
        PjInfoBean pjInfo = pjInfoMapper.selectById(param.get("billId"));
        //判断数据来源
        if (pjInfo != null && (pjInfo.getSourceFlag().equals(SOURCE_INTERNET) || pjInfo.getSourceFlag().equals(SOURCE_WECHAT))) {
            //流程从资料审核驳回到信息登记，修改overruleFlag的值为1，表示驳回,并存储驳回理由
            if (fromNodeCode != null && fromNodeCode.equals(PjInfoService.INFO_APPROVAL)
                    && toNodeCode.equals(PjInfoService.REGISTER)) {
                pjInfo.setOverruleFlag(1);
                pjInfo.setRejectionReason(param.get("comment"));
                pjInfoMapper.updateRegister(pjInfo);
            }
            //流程是已驳回状态，且再次从信息登记提交到资料审核，修改overruleFlag的值为2，表示二次提交
            if (fromNodeCode != null && fromNodeCode.equals(PjInfoService.REGISTER)
                    && toNodeCode.equals(PjInfoService.INFO_APPROVAL)
                    && pjInfo.getOverruleFlag() != null && pjInfo.getOverruleFlag() == 1) {
                pjInfo.setOverruleFlag(2);
                pjInfoMapper.updateRegister(pjInfo);
            }
        }
        if ("2".equals(String.valueOf(param.get("operation")))
                && PjInfoService.INVITATION_ACCEPT.equalsIgnoreCase(fromNodeCode)
                && PjInfoService.INVITATION_ACCEPT.equalsIgnoreCase(toNodeCode)) {
            String relatedUser = param.get("relatedUser");
            String surveyStaff = pjInfo.getSurveyStaff();
            if (surveyStaff.indexOf(",") > -1) {
                List<String> surveyStaffList = Arrays.asList(surveyStaff.split(","));
                int index = surveyStaffList.indexOf(userInfo.getUserInfo().getAcount());
                if (index != -1) {
                    surveyStaffList.set(index, relatedUser);
                }
                surveyStaff = surveyStaffList.stream().collect(Collectors.joining(","));
                pjInfo.setSurveyStaff(surveyStaff);
            } else {
                pjInfo.setSurveyStaff(relatedUser);
            }
            int iCount = pjInfoMapper.updateSurvey(pjInfo);
            if (iCount > 0) {
                logger.info("修改勘察邀约人员成功：{}", surveyStaff);
            }
        }
        /*保存自定义实例时间*/
        WorkDayUtils.save( factory,  userInfo,toNodeCode,pjInfo.getId());
    }
}